/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/
const PENDING ='pending';
const FULFILLED ='fulfilled';
const REJECTED = 'rejected'

class MyPromise {
    constructor(executor) {
        executor(this.resolve,this.reject)
    }
    status = PENDING

    //成功的值
    value = undefined
    //失败的原因
    reason = undefined
    //成功会调
    successCallback  = []
    //失败回调
    failCallback = []
    resolve = value =>{
        if (this.status !== PENDING) return
        this.status = FULFILLED
        this.value = value
        //执行异步
        // this.successCallback && this.successCallback(this.value)
        //截取数组第一个，并返回
        while(this.successCallback.length) this.successCallback.shift()(this.value)
    }
    reject = reason =>{
        if (this.status !== PENDING) return
        this.status = REJECTED
        this.reason = reason
        //执行异步
        // this.failCallback && this.failCallback(this.reason)
        //截取数组第一个，并返回
        while(this.failCallback.length) this.failCallback.shift()(this.value)
    }
    then = (successCallback,failCallback) =>{
        //successCallback,failCallback判断是不是一个函数如果不是转化为函数
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : value => value;
        //实例化一个promise2，并返回他
        let promise2 =new MyPromise((resolve,reject) =>{
            if (this.status  === FULFILLED){
                //判断有没有返回自己
                try {
                           setTimeout(() =>{

                        let result = successCallback(this.value)
                        //判断类型
                        judgeResult(promise2,result,resolve,reject)
                    },0)
                }catch (error){
                        reject(error)
                    }


            }else if (this.status  === REJECTED) {

                   try {
                            setTimeout(() =>{
                    let result =  failCallback(this.reason)

                    //判断类型
                    judgeResult(promise2,result,resolve,reject)
                },0)
                }catch (error){
                        reject(error)
                    }
            }else {
                //此时状态为padding，说明为异步将成功失败储存起来
                //reslove()或reject()最后的地方运行
                //判断有没有返回自己
                this.successCallback.push(() =>{
                    try {
                     setTimeout(() =>{
                            let result = successCallback(this.value)
                            //判断类型
                            judgeResult(promise2,result,resolve,reject)
                        },0)
                    }catch (error){
                            reject(error)
                        }

                })
                //判断有没有返回自己
                this.failCallback.push(() =>{
                     try {
                  setTimeout(() =>{
                        let result = failCallback(this.value)
                        //判断类型
                        judgeResult(promise2,result,resolve,reject)
                    },0)
                }catch (error){
                        reject(error)
                    }


                })
            }
        })
        return promise2
    }

        // Promise.catch就是一个没有成功回调的then
        static catch(failCallback) {
            return this.then(null, failCallback)
        }
        // Promise.all 故名思意，就是等全部，全部成功之后，返回一个Promise对象，成功回调全部返回的数组
        // 如果有失败，则会返回一个Promise对象，失败回调第一个失败的返回
        // 之前采用push，经过好心人提醒，异步会导致返回的结果与原来的Promise对象数组的顺序不一致
        // 改为普通的for循环，使用一个count计数，count == len时，便res(arr)
        static all(array) {
          try {
            if (!(array instanceof Array)) throw(new Error("请传入一个数组"))

            if (array.length == 0) throw(new Error("请不要传入一个空数"))

            let arr = []
            let len = array.length
            let count = 0;
            function addAndJudgeAll(index, value, res) {
              arr[index] = value
              count++
              if (count == len) res(arr)
            }
            return new MyPromise((res, rej) => {
              for(let i = 0; i < len; i++) {
                if (array[i] instanceof MyPromise) {
                  array[i].then(value=> {
                    addAndJudgeAll(i, value, res)
                  }, error => {
                    rej(error)
                  })
                } else {
                  addAndJudgeAll(i, array[i], res)
                }
              }
            })

          } catch (error) {
            console.log(error);
          }
        }
}

function judgeResult(promise2,result,resolve,reject){
    if (promise2 === result){
        return reject('不要返回自己！！！！！！！ss')
    }

    if (result instanceof  MyPromise){
        result.then(value =>resolve(value),error =>reject(error))
    }else {
        resolve(result)
    }
}



